﻿#pragma once
#ifndef WRBUFFER_H
#define WRBUFFER_H

#include "../WRBasics.h"
#include <QAtomicInt>
#ifdef WRDEBUG
#include "../Runtime/WRException.h"
#endif

//表示简单数据缓存。
template <class T> class WRBuffer
{
private:
    //指针。
    T* m_arr;
    //容量。
    WRu m_max;
    //数量。
    WRu m_cnt;
    //引用。
    QAtomicInt m_ref;

    //禁用复制构造函数和赋值操作符。
    Q_DISABLE_COPY(WRBuffer)

    //删除当前数据对象。
    inline ~WRBuffer()
    {
        if (m_arr)
        {
            delete[] m_arr;
        }
    }
    //计算容纳目标数目需要调整的大小。
    inline WRu resize(WRu count)
    {
        count += count / 2;
        WRu left = count % 8;
        if (left) count += count - left;
        if (count < 32) count = 32;
        return count;
    }

public:
    //初始化空缓存数据。
    inline WRBuffer(void) : m_arr(0), m_max(0), m_cnt(0), m_ref(1)
    {
        //add code here
    }
    //初始化指定容量的数据。
    inline WRBuffer(WRu capacity)  : m_arr(new T[capacity]), m_max(capacity), m_cnt(0), m_ref(1)
    {
        //add code here
    }

    //添加对象引用。
    inline void addRef(void)
    {
        m_ref.ref();
    }
    //释放对象引用, 如果引用计数为0，则删除对象，返回True，否则返回False。
    inline bool release(void)
    {
        if (!m_ref.deref())
        {
            delete this;
            return true;
        }
        return false;
    }

    //获取元素数量。
    inline WRu count(void) const
    {
        return m_cnt;
    }

    //获取数据内容。
    inline const T* array(void) const
    {
        return m_arr;
    }
    //获取数据内容。
    inline T* array(void)
    {
        return m_arr;
    }

    //获取指定起始位置的数据。
    inline const T* array(WRu start) const
    {
#ifdef WRDEBUG
        if (start >= m_cnt)
        {
            throw WRArgumentOutOfRangeException();
        }
#endif
        return m_arr + start;
    }
    //获取指定起始位置的数据。
    inline T* array(WRu start)
    {
#ifdef WRDEBUG
        if (start >= m_cnt)
        {
            throw WRArgumentOutOfRangeException();
        }
#endif
        return m_arr + start;
    }

    //获取指定索引处的元素。
    inline const T& index(WRu index) const
    {
#ifdef WRDEBUG
        if (index >= m_cnt)
        {
            throw WRArgumentOutOfRangeException();
        }
#endif
        return m_arr[index];
    }
    //获取指定索引处的元素。
    inline T& index(WRu index)
    {
#ifdef WRDEBUG
        if (index >= m_cnt)
        {
            throw WRArgumentOutOfRangeException();
        }
#endif
        return m_arr[index];
    }

    //清除当前集合中的所有元素。
    inline void clear()
    {
        m_cnt = 0;
    }

    //清除当前缓存并预先分配指定数据量的空间。
    inline void reset(WRu count)
    {
        if (count > m_max)
        {
            if (m_arr)
            {
                delete[] m_arr;
            }
            m_arr = new T[count];
            m_max = count;
        }
        m_cnt = count;
    }

    //向缓存中预分配指定数据量的空间。
    inline void assign(WRu count)
    {
        WRu total = m_cnt + count;
        if (total > m_max)
        {
            WRu max = resize(total);
            T* arr = new T[max];
            if (m_arr)
            {
                memcpy(arr, m_arr, sizeof(T) * m_cnt);
                delete[] m_arr;
            }
            m_arr = arr;
            m_max = max;
        }
        m_cnt = total;
    }

    //向缓存中添加指定数量的元素。
    inline void append(const T* array, WRu count)
    {
        WRu cnt = m_cnt + count;
        if (cnt > m_max)
        {
            WRu max = resize(cnt);
            T* arr = new T[max];
            if (m_arr)
            {
                memcpy(arr, m_arr, sizeof(T) * m_cnt);
                delete[] m_arr;
            }
            m_arr = arr;
            m_max = max;
        }
        memcpy(m_arr + m_cnt, array, sizeof(T) * count);
        m_cnt = cnt;
    }
    //向缓存中添加指定的元素。
    inline void append(const T& value)
    {
        WRu cnt = m_cnt + 1;
        if (cnt > m_max)
        {
            WRu max = resize(cnt);
            T* arr = new T[max];
            if (m_arr)
            {
                memcpy(arr, m_arr, sizeof(T) * m_cnt);
                delete[] m_arr;
            }
            m_arr = arr;
            m_max = max;
        }
        m_arr[m_cnt] = value;
        m_cnt = cnt;
    }

    //移除缓存中从指定索引开始的指定数量的元素。
    inline void remove(WRu start, WRu count)
    {
        WRu index = start + count;
#ifdef WRDEBUG
        if (start >= m_cnt)
        {
            throw WRArgumentOutOfRangeException("start");
        }
        if (index > m_cnt)
        {
            throw WRArgumentOutOfRangeException("count");
        }
#endif
        memmove(m_arr + start, m_arr + index, sizeof(T) * (m_cnt - index));
        m_cnt -= count;
    }
};

#endif // WRBUFFER_H
